package org.unique.plugin.mongo;

import java.util.List;
import java.util.Map;
import java.util.Set;

import org.bson.types.ObjectId;
import org.unique.common.tools.CollectionUtil;
import org.unique.common.tools.JSONUtil;
import org.unique.common.tools.MongoUtil;
import org.unique.common.tools.StringUtils;

import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
import com.mongodb.QueryOperators;

/**
 * mongo操作器
 * @author:rex
 * @date:2014年8月12日
 * @version:1.0
 */
public class MongoExecutor {
	
	/*
	 * 唯一性id
	 */
	private DBObject objectId;
	
	/*
	 * 查询/修改条件
	 */
	private DBObject query;
	
	/*
	 * 排序条件
	 */
	private DBObject order;
	
	/*
	 * 数据库实例
	 */
	private DB db = MongoManager.getBlogDB();
	
	/**
	 * 操作的集合
	 */
	private String collectionName;
	
	public MongoExecutor(String collectionName) {
		this.collectionName = collectionName;
		this.query = new BasicDBObject();
	}
	
	/**
	 * 注入id条件
	 * @param id
	 * @return
	 */
	public MongoExecutor putId(String id) {
		this.objectId = new BasicDBObject("_id", new ObjectId(id));
		return this;
	}
	
	/**
	 * 条件字段/value
	 * @param key
	 * @param value
	 * @return
	 */
	public MongoExecutor put(String key, Object value){
		if(null != value){
			if(value instanceof String && !"".equals(value)){
				this.query.put(key, value);
			} else if(value instanceof Set){
				Set<?> set = (Set<?>) value;
				if(null != set && set.size() > 0){
					this.query.put(key, value);
				}
			} else{
				this.query.put(key, value);
			}
		}
		return this;
	}
	
	/**
	 * 注入map条件
	 * @param map
	 */
	public MongoExecutor(String collectionName, Map<String, Object> map) {
		this.collectionName = collectionName;
		if(!CollectionUtil.isEmpty(map)){
			if(map.containsKey("_id")){
				this.objectId = new BasicDBObject("_id", new ObjectId(map.get("id").toString()));
				map.remove("id");
			}
			this.query = new BasicDBObject(map);
		}
	}
	
	/**
	 * 注入排序字段
	 * @param field 例：name-desc
	 */
	public MongoExecutor order(String field) {
		if(StringUtils.isNotBlank(field)){
			if(field.endsWith("desc")){
				this.order = new BasicDBObject(field.split("-")[0], -1);
			} else{
				this.order = new BasicDBObject(field.split("-")[0], 1);
			}
		} else{
			this.order = new BasicDBObject("_id", -1);
		}
		return this;
	}
	
	/**
	 * 注入in条件
	 * @param field
	 * @param set
	 * @return
	 */
	public MongoExecutor in(String field, Set<String> set) {
		if(null != set && set.size() > 0){
			this.query.put(field,  new BasicDBObject(QueryOperators.IN, set));
		}
		return this;
	}
	
	/**
	 * 注入not in条件
	 * @param field
	 * @param set
	 * @return
	 */
	public MongoExecutor notIn(String field, Set<String> set) {
		if(null != set && set.size() > 0){
			this.query.put(field,  new BasicDBObject(QueryOperators.NIN, set));
		}
		return this;
	}
	
	/**
	 * 注入>条件
	 * @param field
	 * @param value
	 * @return
	 */
	public MongoExecutor gt(String field, Object value) {
		if(null != value){
			this.query.put(field,  new BasicDBObject(QueryOperators.GT, value));
		}
		return this;
	}
	
	/**
	 * 注入>=条件
	 * @param field
	 * @param value
	 * @return
	 */
	public MongoExecutor gte(String field, Object value) {
		if(null != value){
			this.query.put(field,  new BasicDBObject(QueryOperators.GTE, value));
		}
		return this;
	}
	/**
	 * 注入<条件
	 * @param field
	 * @param value
	 * @return
	 */
	public MongoExecutor lt(String field, Object value) {
		if(null != value){
			this.query.put(field,  new BasicDBObject(QueryOperators.LT, value));
		}
		return this;
	}
	
	/**
	 * 注入<=条件
	 * @param field
	 * @param value
	 * @return
	 */
	public MongoExecutor lte(String field, Object value) {
		if(null != value){
			this.query.put(field,  new BasicDBObject(QueryOperators.LTE, value));
		}
		return this;
	}
	
	/**
	 * 查询器
	 * @param collectionName
	 * @return
	 */
	public List<DBObject> find(){
		return db.getCollection(collectionName).find(this.getDBObject()).toArray();
	}
	
	/**
	 * 分页查询器
	 * @param collectionName
	 * @param pageIndex
	 * @param pageSize
	 * @param order
	 * @return
	 */
	public List<DBObject> findByPage(int skip, int limit, String order){
		return db.getCollection(collectionName).
		find(this.getDBObject()).skip(skip).limit(limit).sort(this.getOrder()).toArray();
	}
	
	/**
	 * 保存一条记录
	 * @return
	 */
	public int save() {
		return db.getCollection(collectionName).save(this.getDBObject()).getN();
	}
	
	/**
	 * 保存一条记录
	 * @return
	 */
	public int save(String json) {
		Map<String, Object> map = JSONUtil.json2Map(json);
		return db.getCollection(collectionName).save(MongoUtil.map2DBObject(map)).getN();
	}
	
	/**
	 * 根据主键更新一条记录
	 * @return
	 */
	public int update() {
		return db.getCollection(collectionName).update(this.getObjectId(), this.getDBObject()).getN();
	}
	
	/**
	 * 更新一条记录
	 * @param dbObject
	 * @return
	 */
	public int update(DBObject dbObject) {
		this.objectId = new BasicDBObject("_id", new ObjectId(dbObject.get("_id").toString()));
		return db.getCollection(collectionName).update(this.getObjectId(), dbObject).getN();
	}
	
	/**
	 * 根据主键更新一条记录
	 * @return
	 */
	public int update(String json) {
		Map<String, Object> map = JSONUtil.json2Map(json);
		if (map.containsKey("id")) {
			this.objectId = new BasicDBObject("_id", new ObjectId(map.get("id").toString()));
			map.remove("id");
			return db.getCollection(collectionName).update(this.getObjectId(), MongoUtil.map2DBObject(map)).getN();
		}
		return 0;
	}
	
	/**
	 * 根据主键删除一条记录
	 * @return
	 */
	public int remove(){
		return db.getCollection(collectionName).remove(this.getObjectId()).getN();
	}
	
	/**
	 * 根据主键查询一条记录
	 * @return
	 */
	public DBObject findOne() {
		return db.getCollection(collectionName).findOne(this.getObjectId());
	}
	
	/**
	 * 获取集合连接
	 * @return
	 */
	public DBCollection getDBCollection(){
		return db.getCollection(collectionName);
	}	
	
	public DBObject getDBObject(){
		return this.query;
	}
	
	public DBObject getObjectId(){
		return this.objectId;
	}
	
	public DBObject getOrder() {
		return this.order;
	}

}
